package repo

import (
	"encoding/csv"
	"fmt"
	"os"
)

// SelectionItem 定义了一个可选型项目.
type SelectionItem struct {
	Attrs   map[string]string
	Name    string
	Version string
	License string
	Label   string
}

func NewSelectionItem(headers []string, records []string) *SelectionItem {
	item := &SelectionItem{
		Attrs:   make(map[string]string),
		Name:    "",
		Version: "",
		License: "",
		Label:   "",
	}

	for index, key := range headers {
		if index < len(records) {
			item.Attrs[key] = records[index]
		} else {
			item.Attrs[key] = ""
		}
	}

	item.Name = item.Attrs["软件名称"]
	item.Version = item.Attrs["软件版本"]
	item.License = item.Attrs["开源软件License"]
	item.Label = MakeSelectionLabel(item.Name, item.Version)

	return item
}

// SelectionOrder 定义了可选型项目的清单.
type SelectionOrder struct {
	items  map[string]*SelectionItem
	Titles []string
	Tag    string
	File   string
}

func (s *SelectionOrder) Add(headers []string, columns []string) bool {
	item := NewSelectionItem(headers, columns)
	if _, exist := s.items[item.Label]; exist {
		return false
	}
	s.items[item.Label] = item
	return true
}

func (s *SelectionOrder) Find(name string, version string) (*SelectionItem, bool) {
	item, exist := s.items[MakeSelectionLabel(name, version)]
	if !exist {
		return nil, false
	}
	return item, true
}

func (s *SelectionOrder) Exist(name string, version string) bool {
	_, exist := s.items[MakeSelectionLabel(name, version)]
	return exist
}

func NewSelectionOrder(tag string, file string) *SelectionOrder {
	return &SelectionOrder{
		items:  make(map[string]*SelectionItem),
		Tag:    tag,
		Titles: []string{},
		File:   file,
	}
}

func MakeSelectionLabel(name string, version string) string {
	return fmt.Sprintf("{%v}{%v}", name, version)
}

func ReadSelectionOrder(tag string, filepath string) (*SelectionOrder, error) {
	file, err := os.Open(filepath)
	if err != nil {
		return nil, err
	}

	defer file.Close()

	reader := csv.NewReader(file)

	records, err := reader.ReadAll()
	if err != nil {
		return nil, fmt.Errorf("read data from csv file failed: %v", err)
	}

	if len(records) < 1 {
		return nil, fmt.Errorf("read header from csv file failed: %v", err)
	}

	order := NewSelectionOrder(tag, filepath)
	headers := records[0]
	order.Titles = headers
	for _, columns := range records[1:] {
		order.Add(headers, columns)
	}

	return order, nil
}

func SelectionMatching(trainModuleName string, trainModuleVersion string, selectionOrderList []*SelectionOrder) (int, *SelectionItem, bool) {

	for index, order := range selectionOrderList {
		// 如果已经存在，就没必要了
		selItem, exist := order.Find(trainModuleName, trainModuleVersion)
		if !exist {
			continue
		}

		// 保存选型结果
		//selectionResultMapping[moduleLabel.String()] = &SelectionResult{
		//	Descriptor: descriptor,
		//	Selection:  selItem,
		//	Reason:     nil,
		//}
		return index, selItem, true
	}

	return -1, nil, false
}
